package com.zmn.oms.business.impl.orderamount;

import com.google.common.collect.Lists;
import com.zmn.common.constant.StatusConsts;
import com.zmn.common.utils.amount.AmountUtil;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.math.MathUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.dms.common.enums.DiscountTypeEnums;
import com.zmn.dms.common.enums.coup.ThirdPlatEnum;
import com.zmn.dms.dubbo.interfaces.preferential.PreferentialRemoteService;
import com.zmn.oms.business.interfaces.orderamount.OrderAmountCalcBService;
import com.zmn.oms.business.interfaces.orderamount.OrderDiscountCalcBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.TriggerAmountChangeEnum;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.bo.orderamount.*;
import com.zmn.oms.model.entity.discount.OrderDiscount;
import com.zmn.oms.model.entity.discount.OrderPayDiscount;
import com.zmn.oms.model.entity.factory.OrderFactory;
import com.zmn.oms.model.entity.product.OrderProduct;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.services.interfaces.discount.OrderDiscountService;
import com.zmn.oms.services.interfaces.factory.OrderFactoryService;
import com.zmn.oms.services.interfaces.orderpaydiscount.OrderPayDiscountService;
import com.zmn.oms.services.interfaces.product.OrderProductService;
import com.zmn.pay.common.constant.PayConsts;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 类描述：计算金额
 * @author heciqi
 * @date 2020-06-03 14:13:35
 */
@Service
@Slf4j
public class OrderAmountCalcBServiceImpl implements OrderAmountCalcBService {

	static final String TAG = "OMS-订单和优惠金额计算";
	@Autowired
	private OrderDiscountCalcBService orderDiscountCalcBService;
	@Autowired
	private OrderDiscountService orderDiscountService;
	@Autowired
	private OrderFactoryService orderFactoryService;
	@Autowired
	private OrderProductService orderProductService;
	@Autowired
	private OrderPayDiscountService orderPayDiscountService;

	@Reference(version = com.zmn.dms.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
	private PreferentialRemoteService preferentialRemoteService;

	/**
	 * 获取金额计算入参
	 * @param orderWork
	 * @return
	 */
	@Override
	public ReCalcOrderAmountDIO getReCalcOrderAmountDIO(OrderWork orderWork) {
		ReCalcOrderAmountDIO reCalcOrderAmountDIO = new ReCalcOrderAmountDIO();
		OrderAmountDIO orderAmountDIO = BeanMapper.map(orderWork, OrderAmountDIO.class);
		reCalcOrderAmountDIO.setFinalPrice(orderWork.getFinalPrice());
		reCalcOrderAmountDIO.setOrderAmountDIO(orderAmountDIO);
		reCalcOrderAmountDIO.setDiscountConditionParamsDIO(BeanMapper.map(orderWork, DiscountConditionParamsDIO.class));
		List<OrderDiscount> orderDiscountList = orderDiscountService.listByOrderIdSrcMaster(orderWork.getOrderId());
		reCalcOrderAmountDIO.setOrderDiscountList(orderDiscountList);
		if (CollectionUtil.isNotNullOrEmpty(orderDiscountList) && NumberUtil.isNullOrZero(orderAmountDIO.getDiscountAmount())) {
			int discountAmount = orderDiscountList.stream()
					.filter(e -> Objects.nonNull(e.getAmount()))
					.mapToInt(e -> e.getAmount()).sum();
			orderAmountDIO.setDiscountAmount(discountAmount);
		}

		List<OrderPayDiscount> orderPayDiscountList = orderPayDiscountService.listOrderPayDiscountByOrderId(orderWork.getOrderId());
		reCalcOrderAmountDIO.setOrderPayDiscountList(orderPayDiscountList);
		if (CollectionUtil.isNotNullOrEmpty(orderPayDiscountList) && NumberUtil.isNullOrZero(orderAmountDIO.getPayDiscountAmount())) {
			int payDiscountAmount = orderPayDiscountList.stream()
					.filter(e -> Objects.nonNull(e.getAmount()))
					.mapToInt(e -> e.getAmount()).sum();
			orderAmountDIO.setPayDiscountAmount(payDiscountAmount);
		}

		// 处理次卡信息
		if (CollectionUtil.isNotNullOrEmpty(orderDiscountList)) {
			orderDiscountList.stream()
					.filter(e -> Objects.equals(e.getCateg(), DiscountTypeEnums.DISCOUNT_COUP_ONCECARD.getSubType())).findFirst()
					.ifPresent(orderDiscount -> reCalcOrderAmountDIO.setOnceCardcouponCode(orderDiscount.getItemCode()));
		}

		// 品牌
		List<OrderProduct> orderProducts = orderProductService.listOrderProductByOrderIdSrcMaster(orderWork.getOrderId());
		reCalcOrderAmountDIO.setBrandId(orderProducts.get(0).getBrandId());

		// 保内单，userId为厂商用户的userId
		if (Objects.equals(orderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_F)) {
			OrderFactory orderFactory = orderFactoryService.findOrderFactoryByKey(orderWork.getOrderId());
			if (orderFactory != null) {
				reCalcOrderAmountDIO.getDiscountConditionParamsDIO().setUserId(orderFactory.getFcUserId());
			} else {
				log.error("厂商单未找到厂商工单数据[{}]", orderWork.getOrderId());
			}
		}

		// 处理一口价类型 当servItemType为4 并且finalPrice为2的时候，servItemType传5
        if (Objects.equals(orderWork.getServItemType(), OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE)
                && Objects.equals(orderWork.getFinalPrice(), GlobalConsts.YES)) {
            reCalcOrderAmountDIO.getDiscountConditionParamsDIO().setServItemType(OrderConsts.SERVICE_ITEM_TYPE_FINAL_PRICE);
        }

		return reCalcOrderAmountDIO;
	}
	/**
	 * 下单
	 * 计算工单和优惠金额
	 *
	 * @return
	 */
	@Override
	public OrderAmountCalcBO calcOrderAmountAndDiscountAmount(CalcAddOrderAmountDIO calcOrderAmountDIO, List<OrderDiscount> orderDiscountList, List<OrderPayDiscount> orderPayDiscountList) {
		// 返修单金额
		if (Objects.equals(calcOrderAmountDIO.getDiscountConditionParamsDIO().getType(), OrderConsts.ORDER_TYPE_REWORK)) {
			OrderAmountCalcBO build = OrderAmountCalcBO.builder().channelPrepayAmount(calcOrderAmountDIO.getOrderAmountDIO().getChannelPrepayAmount()).build();
			return build;
		}

		// 1，计算优惠
		OrderDiscountCalcBO orderDiscountCalcBO = orderDiscountCalcBService.calcAddOrderDiscount(calcOrderAmountDIO, orderDiscountList);

		// 1.1 计算支付优惠
		int payDiscountAmount = 0;
		if (CollectionUtil.isNotNullOrEmpty(orderPayDiscountList)) {
			payDiscountAmount = orderPayDiscountList.stream().mapToInt(OrderPayDiscount::getAmount).sum();
		}

		OrderAmountDIO orderAmountDIO = calcOrderAmountDIO.getOrderAmountDIO();
		Integer originalAmount = orderAmountDIO.getOriginalAmount();
		int discountAmount = orderDiscountCalcBO != null ? Optional.ofNullable(orderDiscountCalcBO.getDiscountAmount()).orElse(0) : 0;
		int discountPrepayAmount = orderDiscountCalcBO != null ? Optional.ofNullable(orderDiscountCalcBO.getDiscountPrepayAmount()).orElse(0) : 0;

		// 2，计算师傅收款
		Integer masterAmount = null;
		if (NumberUtil.isNotNullOrZero(originalAmount)) {
			// 渠道预收情况
			if (NumberUtil.isNotNullOrZero(orderAmountDIO.getChannelPrepayAmount())) {
				if (orderAmountDIO.getChannelPrepayAmount() > originalAmount) {// 渠道预付金额>大于原价-------->清空原价
					originalAmount = null;
				} else {
					masterAmount = MathUtil.sub(originalAmount.intValue(), discountAmount);
					masterAmount = MathUtil.sub(masterAmount, orderAmountDIO.getChannelPrepayAmount());
					masterAmount = MathUtil.sub(masterAmount.intValue(), discountPrepayAmount);
					masterAmount = MathUtil.sub(masterAmount.intValue(), payDiscountAmount);
				}
			}
			// 平台预收情况
			else {
				masterAmount = MathUtil.sub(originalAmount.intValue(), discountAmount);
				masterAmount = MathUtil.sub(masterAmount, orderAmountDIO.getPrepayAmount());
				masterAmount = MathUtil.sub(masterAmount.intValue(), discountPrepayAmount);
				masterAmount = MathUtil.sub(masterAmount.intValue(), payDiscountAmount);
				if (masterAmount < 0) {
					masterAmount = 0;
				}
			}
		}

		// 3，计算应收
		Integer totalAmount = null;
		if (NumberUtil.isNotNullOrZero(originalAmount)) {
			// 应收 = 原价-优惠 + 增值产品预售金额)
			totalAmount = MathUtil.sub(originalAmount.intValue(), discountAmount);
			totalAmount = MathUtil.sub(totalAmount.intValue(), payDiscountAmount);
			totalAmount += Optional.ofNullable(discountPrepayAmount).orElse(0);
		}

		OrderAmountCalcBO orderAmountCalcBO = new OrderAmountCalcBO();
		orderAmountCalcBO.setOriginalAmount(originalAmount);
		orderAmountCalcBO.setTotalAmount(totalAmount);
		orderAmountCalcBO.setPrepayAmount(orderAmountDIO.getPrepayAmount());
		orderAmountCalcBO.setChannelPrepayAmount(orderAmountDIO.getChannelPrepayAmount());
		orderAmountCalcBO.setMasterAmount(masterAmount);
		orderAmountCalcBO.setPayDiscountAmount(payDiscountAmount);
		Integer disAmount = orderDiscountCalcBO != null ? Optional.ofNullable(orderDiscountCalcBO.getDiscountAmount()).orElse(0) : 0;// 优惠总额
		orderAmountCalcBO.setDiscountAmount(disAmount == 0 ? null : disAmount);
		orderAmountCalcBO.setDiscountPrepayAmount(orderDiscountCalcBO != null ? Optional.ofNullable(orderDiscountCalcBO.getDiscountPrepayAmount()).orElse(0) : 0);
		orderAmountCalcBO.setOrderDiscountCalcBO(orderDiscountCalcBO);

		if (NumberUtil.isNotNullOrZero(originalAmount)) {
			// 已付金额全款（平台收款，渠道收款，优惠）
			Integer paidAmount = Optional.ofNullable(orderAmountDIO.getPrepayAmount()).orElse(0) + disAmount + payDiscountAmount;
			// 渠道已付金额全款（渠道收款，优惠）
			Integer channelPaidAmount = Optional.ofNullable(orderAmountDIO.getChannelPrepayAmount()).orElse(0) + disAmount + payDiscountAmount;

			// 原价和已付金额相等，不计算优惠
			orderAmountCalcBO.setFullPaymentFlag(GlobalConsts.NO);

			// 是否次卡订单并且预付款为0
			boolean isTimesWork = false;
			if (Objects.nonNull(orderDiscountCalcBO) && CollectionUtil.isNotNullOrEmpty(orderDiscountCalcBO.getOrderDiscountList())) {
				isTimesWork = orderDiscountCalcBO.getOrderDiscountList().stream().anyMatch(e -> Objects.equals(e.getCateg(), DiscountTypeEnums.DISCOUNT_COUP_ONCECARD.getSubType()));
			}

			// 如果是次卡订单，并且预付款为0，标记为不是预付全款
			if (isTimesWork && NumberUtil.isNullOrZero(orderAmountDIO.getPrepayAmount()) && NumberUtil.isNullOrZero(orderAmountDIO.getChannelPrepayAmount())) {
				orderAmountCalcBO.setFullPaymentFlag(GlobalConsts.NO);
			} else if (Objects.equals(originalAmount, paidAmount) || Objects.equals(originalAmount, channelPaidAmount)) {
				orderAmountCalcBO.setFullPaymentFlag(GlobalConsts.YES);
			}
		}

		log.info("{}结果===>{}", TAG, orderAmountCalcBO);
		return orderAmountCalcBO;
	}

	/**
	 * 下单后
	 * 重新计算工单和优惠金额
	 *
	 * @param triggerAmountChangeEnum 触发节点
	 * @param reCalcOrderAmountDIO
	 * @return
	 */
	@Override
	public OrderAmountCalcBO reCalcOrderAmountAndDiscountAmount(TriggerAmountChangeEnum triggerAmountChangeEnum, ReCalcOrderAmountDIO reCalcOrderAmountDIO, Integer compulsoryFlag) throws OmsBaseException {
		log.info("[{}]，触发计算订单[{}]，入参[{}]", triggerAmountChangeEnum.getName(), TAG, reCalcOrderAmountDIO);

		DiscountConditionParamsDIO discountConditionParamsDIO = reCalcOrderAmountDIO.getDiscountConditionParamsDIO();

		// 返修单金额
		if (Objects.equals(discountConditionParamsDIO.getType(), OrderConsts.ORDER_TYPE_REWORK)) {
			OrderAmountCalcBO build = OrderAmountCalcBO.builder().originalAmount(0).totalAmount(0).masterAmount(0).build();
			return build;
		}

		OrderAmountDIO orderAmountDIO = reCalcOrderAmountDIO.getOrderAmountDIO();
		List<OrderDiscount> selectedOrderDiscountList = reCalcOrderAmountDIO.getOrderDiscountList();
		OrderDiscountCalcBO orderDiscountCalcBO = null;
		switch (triggerAmountChangeEnum) {
			case MODIFY_ORDER_AMOUNT:
			case ARTIFICIAL_OPERATE_FREE_DISCOUNT:
			case MASTER_VISIT:
			case EXTENDED_WARRANTY:
			case VALIDATE_COUPON:
			case REFRESH_DISCOUNT:
			case CLAIM_ORDER:
			case ARTIFICIAL_MASTER_DISCOUNT_PROM:
				// 下单时全款不重新计算优惠
				if (Objects.equals(GlobalConsts.YES, orderAmountDIO.getFullPaymentFlag()) && !Objects.equals(reCalcOrderAmountDIO.getFinalPrice(), GlobalConsts.YES)) {
					break;
				}

				// 如果存在口碑券则不重新请求优惠
				boolean existKBDiscount = Optional.ofNullable(selectedOrderDiscountList).orElse(Collections.emptyList()).stream().anyMatch(e -> Objects.equals(e.getThirdCode(), GlobalConsts.YES));
				if (existKBDiscount) {
					break;
				}

				// 延保
				if (Objects.equals(TriggerAmountChangeEnum.EXTENDED_WARRANTY,triggerAmountChangeEnum)) {
					reCalcOrderAmountDIO.getDiscountConditionParamsDIO().setMember(GlobalConsts.YES);
				}

				// 设置特殊优惠标示
				if (this.isSpecialDiscount(triggerAmountChangeEnum,reCalcOrderAmountDIO)) {
					reCalcOrderAmountDIO.getDiscountConditionParamsDIO().setSpecialDiscountFlag(GlobalConsts.YES);
				}

				// 重新计算优惠
				if (Objects.equals(triggerAmountChangeEnum, TriggerAmountChangeEnum.ARTIFICIAL_MASTER_DISCOUNT_PROM)) {
					orderDiscountCalcBO = orderDiscountCalcBService.reCalcDiscountWithNoVerify(reCalcOrderAmountDIO);
				} else if (StringUtil.isBlank(reCalcOrderAmountDIO.getOnceCardcouponCode())) { // 非次卡订单重新请求优惠
					orderDiscountCalcBO = orderDiscountCalcBService.reCalcDiscount(reCalcOrderAmountDIO);
				}

				// 验券
				if (Objects.equals(TriggerAmountChangeEnum.VALIDATE_COUPON,triggerAmountChangeEnum)) {
					if (orderDiscountCalcBO != null) {
						orderDiscountCalcBO.setCompulsoryFlag(compulsoryFlag);
						//this.setDiscountSellAmount(reCalcOrderAmountDIO, orderDiscountCalcBO); // 设置获取外部券售价
						reCalcOrderAmountDIO.setNewChannelPrepayAmount(this.getThirdCodeSellAmount(reCalcOrderAmountDIO, orderDiscountCalcBO));// 获取外部券售价，作为渠道预收
					}
				}
				break;
			case DELETE_ORDER_AMOUNT:
				orderDiscountCalcBO = orderDiscountCalcBService.getDeleteAllDiscount(selectedOrderDiscountList, orderAmountDIO.getFullPaymentFlag());
				return this.getDeleteOriginalAmountCalcBO(orderDiscountCalcBO, orderAmountDIO);
			case ARTIFICIAL_OPERATE_DISCOUNT:
			case ARTIFICIAL_MASTER_DISCOUNT:
				orderDiscountCalcBO = orderDiscountCalcBService.getArtificialDiscount(triggerAmountChangeEnum, reCalcOrderAmountDIO);
				break;
			case ARTIFICIAL_DISCOUNT_DELETE:
				orderDiscountCalcBO = orderDiscountCalcBService.getDeleteArtificialDiscount(selectedOrderDiscountList);
				break;
			case ARTIFICIAL_MASTER_DISCOUNT_DELETE:
				orderDiscountCalcBO = orderDiscountCalcBService.getDeleteMaterArtificialDiscount(selectedOrderDiscountList);
				break;
			case CHANNEL_SECOND_PAY:// TODO -lhl

				break;
			case TIMES_DISCOUNT_ADD:
				// 检查是否有次卡优惠券ID
				if (StringUtil.isBlank(reCalcOrderAmountDIO.getOnceCardcouponCode())) {
					break;
				}
				orderDiscountCalcBO = orderDiscountCalcBService.reCalcDiscount(reCalcOrderAmountDIO);

				break;
			case TIMES_DISCOUNT_DELETE:
				if (StringUtil.isBlank(reCalcOrderAmountDIO.getOnceCardcouponCode())) {
					break;
				}
				reCalcOrderAmountDIO.setOnceCardcouponCode(null);
				orderDiscountCalcBO = orderDiscountCalcBService.reCalcDiscount(reCalcOrderAmountDIO);
				break;
			default:
				break;
		}

		Integer originalAmount = reCalcOrderAmountDIO.getNewOriginalAmount() != null ? reCalcOrderAmountDIO.getNewOriginalAmount() : Optional.ofNullable(orderAmountDIO.getOriginalAmount()).orElse(0);// 订单金额
		Integer depositAmount = reCalcOrderAmountDIO.getNewDepositAmount() != null ? reCalcOrderAmountDIO.getNewDepositAmount() : Optional.ofNullable(orderAmountDIO.getDepositAmount()).orElse(0);// 定金
		Integer prepayAmount = Optional.ofNullable(orderAmountDIO.getPrepayAmount()).orElse(0);// 啄木鸟预收
		Integer channelPrepayAmount = reCalcOrderAmountDIO.getNewChannelPrepayAmount() != null ? reCalcOrderAmountDIO.getNewChannelPrepayAmount() : Optional.ofNullable(orderAmountDIO.getChannelPrepayAmount()).orElse(0);     // 渠道预收
		Integer discountAmount = orderDiscountCalcBO != null ? Optional.ofNullable(orderDiscountCalcBO.getDiscountAmount()).orElse(0) : Optional.ofNullable(orderAmountDIO.getDiscountAmount()).orElse(0);// 优惠总额
		Integer refundAmount = Optional.ofNullable(orderAmountDIO.getRefundAmount()).orElse(0);// 退款总额
		Integer payDiscountAmount = Optional.ofNullable(orderAmountDIO.getPayDiscountAmount()).orElse(0);//

		// 次卡优惠券抵消金额
		// 自己查询 以价格系统取到的最新的为准
		Integer discountPrepayAmount = orderDiscountCalcBO != null ? 0 : Optional.ofNullable(orderAmountDIO.getDiscountPrepayAmount()).orElse(0);// 优惠预付总额

		// 优惠接口返回的次卡售价
		if (orderDiscountCalcBO != null && CollectionUtil.isNotNullOrEmpty(orderDiscountCalcBO.getOrderDiscountList())) {
			Optional<OrderDiscount> discountOptional = orderDiscountCalcBO.getOrderDiscountList().stream().filter(discount -> {
				return Objects.equals(discount.getCateg(), DiscountTypeEnums.DISCOUNT_COUP_ONCECARD.getSubType());
			}).findFirst();
			if (discountOptional.isPresent()) {
				discountPrepayAmount = Optional.ofNullable(discountOptional.get().getTimesCardSellAmount()).orElse(discountOptional.get().getSellAmount());
				if (NumberUtil.isNullOrZero(discountPrepayAmount)) {
					discountPrepayAmount = orderDiscountCalcBO != null ? 0 : Optional.ofNullable(orderAmountDIO.getDiscountPrepayAmount()).orElse(0);// 优惠预付总额
				}
			}
		} else if ((orderDiscountCalcBO != null && CollectionUtil.isNullOrEmpty(orderDiscountCalcBO.getOrderDiscountList()))) {
			discountPrepayAmount = 0;
		}


		// 验证金额
		if (!Objects.equals(reCalcOrderAmountDIO.getFinalPrice(), GlobalConsts.YES)) {
			validateWorkAmount(originalAmount,discountAmount,prepayAmount,channelPrepayAmount,depositAmount, discountPrepayAmount, payDiscountAmount);
		}

		// 原价不为空才计算应收和尾款
		Integer masterAmount = null;
		Integer totalAmount = null;

		if (NumberUtil.isNotNullOrZero(originalAmount)) {
			// 工程师收款金额 = 订单金额 - (优惠总额 + 平台预收 + 渠道预收 + 定金 + 退款金额 + 优惠券预付)
			Integer addAmount = depositAmount + prepayAmount + channelPrepayAmount + discountAmount + refundAmount + payDiscountAmount;

			// 师傅收款
			if (Objects.equals(discountConditionParamsDIO.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_C)
					&& Objects.equals(orderAmountDIO.getMasterPayStatus(), PayConsts.PAY_STATUS_DONE)) {// 保外单-工程师收款已支付，金额计入渠道预收
				channelPrepayAmount = originalAmount - Optional.ofNullable(orderAmountDIO.getMasterAmount()).orElse(0) + discountAmount + prepayAmount + channelPrepayAmount + depositAmount + refundAmount + payDiscountAmount;
				masterAmount = orderAmountDIO.getMasterAmount();
			} else {
				masterAmount = originalAmount - addAmount;

				// 处理支付优惠金额（payDiscountAmount）
				if (Objects.equals(reCalcOrderAmountDIO.getFinalPrice(), GlobalConsts.YES) && NumberUtil.isNotNullOrZero(payDiscountAmount) && masterAmount < 0) {
					int absMasterAmount = Math.abs(masterAmount);
					if (payDiscountAmount >= absMasterAmount) {
						// 退款完全由支付优惠造成
						payDiscountAmount -= absMasterAmount;
						masterAmount = 0;
					} else {
						// 退款部分由支付优惠造成
						masterAmount += payDiscountAmount;
						payDiscountAmount = 0;
					}

				}

			}

			// 无退款，做合法验证
			if (refundAmount == 0) {
				int minAmount = discountAmount + prepayAmount + channelPrepayAmount + depositAmount + Optional.ofNullable(masterAmount).orElse(0) + payDiscountAmount;// 最小合法金额
				int sub = originalAmount - minAmount;
				if (Objects.equals(reCalcOrderAmountDIO.getFinalPrice(), GlobalConsts.YES)) {
					// 一口价不做小于0校验 TODO
				}else {
					if (sub < 0) {
						throw new OmsBaseException(String.format("总价不能小于：%.2f元", AmountUtil.fen2Yuan(minAmount).doubleValue()));
					}
				}
			}

			// 要先计算payDiscountAmount
			// 订单收入 = 订单金额 - 优惠总额
			totalAmount = originalAmount - discountAmount - refundAmount + discountPrepayAmount - payDiscountAmount;
		}

		OrderAmountCalcBO orderAmountCalcBO = new OrderAmountCalcBO();
		orderAmountCalcBO.setTriggerAmountChangeEnum(triggerAmountChangeEnum);
		orderAmountCalcBO.setOriginalAmount(originalAmount == 0 ? null : originalAmount);
		orderAmountCalcBO.setTotalAmount(totalAmount);
		orderAmountCalcBO.setPrepayAmount(orderAmountDIO.getPrepayAmount());
		orderAmountCalcBO.setChannelPrepayAmount(channelPrepayAmount == 0 ? null : channelPrepayAmount);
		orderAmountCalcBO.setDepositAmount(depositAmount == 0 ? null : depositAmount);
		orderAmountCalcBO.setDiscountAmount(discountAmount == 0 ? null : discountAmount);
		orderAmountCalcBO.setMasterAmount(masterAmount);
		orderAmountCalcBO.setDiscountPrepayAmount(discountPrepayAmount == 0 ? null : discountPrepayAmount);
		orderAmountCalcBO.setOnlyVisit(reCalcOrderAmountDIO.getOnlyVisit());
		orderAmountCalcBO.setOrderDiscountCalcBO(orderDiscountCalcBO);
		orderAmountCalcBO.setPayDiscountAmount(payDiscountAmount);
		log.debug("[{}]，触发计算订单[{}]，出参[{}]", triggerAmountChangeEnum.getName(), TAG, orderAmountCalcBO);
		return orderAmountCalcBO;
	}


	/**
	 * 获取删除原价的订单金额BO
	 * @param orderDiscountCalcBO
	 * @param orderAmountDIO
	 * @return
	 */
	public OrderAmountCalcBO getDeleteOriginalAmountCalcBO(OrderDiscountCalcBO orderDiscountCalcBO, OrderAmountDIO orderAmountDIO) {
		OrderAmountCalcBO orderAmountCalcBO = new OrderAmountCalcBO();
		orderAmountCalcBO.setOriginalAmount(null);
		orderAmountCalcBO.setTotalAmount(null);
		orderAmountCalcBO.setPrepayAmount(orderAmountDIO.getPrepayAmount());
		orderAmountCalcBO.setChannelPrepayAmount(orderAmountDIO.getChannelPrepayAmount());
		orderAmountCalcBO.setDepositAmount(Objects.equals(orderAmountDIO.getDepositStatus(), PayConsts.PAY_STATUS_DONE) ? orderAmountDIO.getDepositAmount() : null);
		Integer discountAmount = orderDiscountCalcBO != null ? Optional.ofNullable(orderDiscountCalcBO.getDiscountAmount()).orElse(0) : 0;// 优惠总额
		orderAmountCalcBO.setDiscountAmount(discountAmount==0? null : discountAmount);
		orderAmountCalcBO.setMasterAmount(null);
		orderAmountCalcBO.setOrderDiscountCalcBO(orderDiscountCalcBO);
		return orderAmountCalcBO;
	}

	/**
	 * 重新计算价格
	 *
	 * @param reCalcOrderAmountDIO
	 * @return
	 */
	public OrderAmountCalcBO reCalcAmount(ReCalcOrderAmountDIO reCalcOrderAmountDIO) {
		int discountAmount = Optional.ofNullable(reCalcOrderAmountDIO.getOrderDiscountList()).orElse(Lists.newArrayList())
				.stream()
				.mapToInt(e -> e.getAmount())
				.sum();

		OrderAmountDIO orderAmountDIO = reCalcOrderAmountDIO.getOrderAmountDIO();
		Integer masterAmount = orderAmountDIO.getMasterAmount();
		Integer totalAmount = null;
		if (NumberUtil.isNotNullOrZero(orderAmountDIO.getOriginalAmount())) {
			int addAmount = Optional.ofNullable(orderAmountDIO.getPrepayAmount()).orElse(0) +
					Optional.ofNullable(orderAmountDIO.getChannelPrepayAmount()).orElse(0) +
					Optional.ofNullable(orderAmountDIO.getDepositAmount()).orElse(0);
			Optional.ofNullable(orderAmountDIO.getDiscountPrepayAmount()).orElse(0);
			totalAmount = orderAmountDIO.getOriginalAmount().intValue() - discountAmount;
			masterAmount = orderAmountDIO.getOriginalAmount() - addAmount - discountAmount;
		}

		OrderAmountCalcBO orderAmountCalcBO = new OrderAmountCalcBO();
		orderAmountCalcBO.setOriginalAmount(orderAmountDIO.getOriginalAmount());
		orderAmountCalcBO.setPrepayAmount(orderAmountDIO.getPrepayAmount());
		orderAmountCalcBO.setChannelPrepayAmount(orderAmountDIO.getChannelPrepayAmount());
		orderAmountCalcBO.setDepositAmount(orderAmountDIO.getDepositAmount());
		orderAmountCalcBO.setDiscountPrepayAmount(orderAmountDIO.getDiscountPrepayAmount());
		orderAmountCalcBO.setPayDiscountAmount(orderAmountDIO.getPayDiscountAmount());
		orderAmountCalcBO.setTotalAmount(Objects.equals(totalAmount, 0) ? null : totalAmount);
		orderAmountCalcBO.setDiscountAmount(Objects.equals(discountAmount, 0) ? null : discountAmount);
		orderAmountCalcBO.setMasterAmount(Objects.equals(masterAmount, 0) ? null : masterAmount);
		log.info("{}重新计算后--->{}", reCalcOrderAmountDIO, orderAmountCalcBO);
		return orderAmountCalcBO;
	}

	private void setDiscountSellAmount(ReCalcOrderAmountDIO reCalcOrderAmountDIO, OrderDiscountCalcBO orderDiscountCalcBO)  throws OmsBaseException{
		List<OrderDiscount> list = orderDiscountCalcBO.getOrderDiscountList();
		if (CollectionUtil.isNullOrEmpty(list)) {
			return;
		}

		List<OrderDiscount> collect = list.stream().filter(e -> Objects.equals(e.getThirdCode(), GlobalConsts.YES)).collect(Collectors.toList());
		if (CollectionUtil.isNullOrEmpty(collect)) {
			return;
		}

		OrderDiscount orderDiscount = collect.get(0);
		// 口碑，，额哦提阿门验券-特殊需要核销才能获取销售价格
		if (Objects.equals(orderDiscount.getThirdCoupPlat(), ThirdPlatEnum.THIRD_COUP_TYPE_KB.getKey())
				|| Objects.equals(orderDiscount.getThirdCoupPlat(), ThirdPlatEnum.THIRD_COUP_TYPE_MT.getKey())) {
			// 核销
			OrderWork orderWork = BeanMapper.map(reCalcOrderAmountDIO.getDiscountConditionParamsDIO(), OrderWork.class);
			Integer salePrice = orderDiscountCalcBService.receiptConsumeDiscount(orderDiscountCalcBO.getReceiptConsumeDiscountList(), reCalcOrderAmountDIO.getInvoker(), reCalcOrderAmountDIO.getOrderAmountDIO().getOriginalAmount(), orderWork, null,GlobalConsts.SPLITER_EMPTY,GlobalConsts.SPLITER_EMPTY);
			log.info("setDiscountSellAmount 平台[{}] 外部券----实际优惠金额==>actualOrderAmount[{}]减去售价[{}]", orderDiscount.getThirdCoupPlat(), orderDiscount.getAmount(), salePrice);
			if (salePrice != null && Objects.equals(orderDiscount.getThirdCoupPlat(), ThirdPlatEnum.THIRD_COUP_TYPE_KB.getKey())) {
				// 口碑才去计算核销的售价
				Integer actualOrderAmount = orderDiscount.getAmount();
				orderDiscount.setAmount(actualOrderAmount < 0 ? 0 : actualOrderAmount);
				orderDiscount.setSellAmount(salePrice);
				orderDiscountCalcBO.setDiscountAmount(list.stream().filter(e -> e.getAmount() != null).mapToInt(OrderDiscount::getAmount).sum());// 优惠总金额
			}
		}
	}
	/**
	 * 获取外部券的售价
	 *
	 * @param orderDiscountCalcBO
	 * @return
	 */
	private Integer getThirdCodeSellAmount(ReCalcOrderAmountDIO reCalcOrderAmountDIO, OrderDiscountCalcBO orderDiscountCalcBO) throws OmsBaseException {

		List<OrderDiscount> list = orderDiscountCalcBO.getOrderDiscountList();
		if (CollectionUtil.isNullOrEmpty(list)) {
			return null;
		}

		List<OrderDiscount> collect = list.stream().filter(e -> Objects.equals(e.getThirdCode(), GlobalConsts.YES)).collect(Collectors.toList());
		if (CollectionUtil.isNullOrEmpty(collect)) {
			return null;
		}

		// 只考虑一个外部券情况
		OrderDiscount orderDiscount = collect.get(0);

		// 口碑验券-特殊需要核销才能获取销售价格
		if (Objects.equals(orderDiscount.getThirdCoupPlat(), ThirdPlatEnum.THIRD_COUP_TYPE_KB.getKey())
				|| Objects.equals(orderDiscount.getThirdCoupPlat(), ThirdPlatEnum.THIRD_COUP_TYPE_MT.getKey())) {
			// 核销
			OrderWork orderWork = BeanMapper.map(reCalcOrderAmountDIO.getDiscountConditionParamsDIO(), OrderWork.class);
			Integer salePrice = orderDiscountCalcBService.receiptConsumeDiscount(orderDiscountCalcBO.getReceiptConsumeDiscountList(), reCalcOrderAmountDIO.getInvoker(), reCalcOrderAmountDIO.getOrderAmountDIO().getOriginalAmount(), orderWork, orderDiscountCalcBO.getCompulsoryFlag(),reCalcOrderAmountDIO.getExternalShopId(),reCalcOrderAmountDIO.getCalledNumber());
			log.info("外部券----实际优惠金额==>actualOrderAmount[{}]减去售价[{}]", orderDiscount.getAmount(), salePrice);
			if (salePrice != null) {
				Integer actualOrderAmount = orderDiscount.getAmount() - salePrice;
				// 实际优惠金额比售价还小，售价用实际优惠金额
				if (orderDiscount.getAmount() < salePrice) {
					log.info("实际优惠金额低于售价，售价用实际优惠金额");
					salePrice = orderDiscount.getAmount();
				}
				orderDiscount.setAmount(actualOrderAmount < 0 ? 0 : actualOrderAmount);
				orderDiscount.setSellAmount(salePrice);
				orderDiscountCalcBO.setDiscountAmount(list.stream().filter(e -> e.getAmount() != null).mapToInt(OrderDiscount::getAmount).sum());// 优惠总金额
				return salePrice;
			}
		}

		return orderDiscount.getSellAmount();
/*		Integer sellAmount = null;
		try {

			return orderDiscount.getSellAmount();
			// 面值：100，售价：9.9
			// 营销接口计算：actualOrderAmount 实际优惠：100-9.9。discountAmount 面值金额：100 。工单得到售价作为渠道成本
			PreferentialDetailDRO preferentialDetailDRO = JSON.parseObject(orderDiscount.getSourceData(), PreferentialDetailDRO.class);
			if (preferentialDetailDRO.getActualOrderAmount() != null
					&& preferentialDetailDRO.getDiscountAmount() != null) {
				if (preferentialDetailDRO.getDiscountAmount() > preferentialDetailDRO.getActualOrderAmount()) {
					sellAmount = preferentialDetailDRO.getDiscountAmount() - preferentialDetailDRO.getActualOrderAmount();
				} else if (preferentialDetailDRO.getDiscountAmount() == preferentialDetailDRO.getActualOrderAmount()) {
					sellAmount = preferentialDetailDRO.getDiscountAmount();
				}
			}
		} catch (Exception ex) {
			log.error("外部券计算失败",ex.getMessage(), ex);
		}
		return sellAmount;*/
	}
	/**
	 * 校验工单边界值
	 * @param originalAmount      订单金额
	 * @param discountAmount      优惠总金额
	 * @param prepayAmount        啄木鸟预付
	 * @param channelPrepayAmount 渠道预付
	 * @param depositAmount       定金
	 * @throws OmsBaseException
	 */
	private void validateWorkAmount(
			Integer originalAmount,
			Integer discountAmount,
			Integer prepayAmount,
			Integer channelPrepayAmount,
			Integer depositAmount,
			Integer discountPrepayAmount,
			Integer payDiscountAmount) throws OmsBaseException {

		// 原价小于等于的情况下，不做判断
		if (originalAmount <= 0) {
			return;
		}

		// 边界公式：订单金额 ≥ 优惠 + 预付款 + 定金
		// 不满足公式，非标准单提示：原价需大于：xx
		// 不满足公式，标准单提示：定金需小于：xx

		// 最小合法金额
		int minValidAmount = discountAmount + prepayAmount + channelPrepayAmount + depositAmount + payDiscountAmount;
		int sub = originalAmount - minValidAmount;
		if (sub < 0) {
			throw new OmsBaseException(StatusConsts.STATUS_SUCCESS_NEXT, String.format("服务项目价格需大于：%.2f元", AmountUtil.fen2Yuan(minValidAmount).doubleValue()));
		}
	}

	/**
	 * 是否设置特殊标识
	 * @param triggerAmountChangeEnum
	 * @param reCalcOrderAmountDIO
	 * @return
	 */
	private boolean isSpecialDiscount(TriggerAmountChangeEnum triggerAmountChangeEnum, ReCalcOrderAmountDIO reCalcOrderAmountDIO) {
		// 全免优惠，认领，刷新操作 设置特殊标识
		if (Objects.equals(TriggerAmountChangeEnum.ARTIFICIAL_OPERATE_FREE_DISCOUNT,triggerAmountChangeEnum)
				|| Objects.equals(TriggerAmountChangeEnum.CLAIM_ORDER,triggerAmountChangeEnum)
				|| Objects.equals(TriggerAmountChangeEnum.REFRESH_DISCOUNT,triggerAmountChangeEnum)) {
			return true;
		}

		// 价格相等&&没有优惠，设置特殊标识
		Integer currOriginalAmt = Optional.ofNullable(reCalcOrderAmountDIO.getNewOriginalAmount())
				.orElse(reCalcOrderAmountDIO.getOrderAmountDIO().getOriginalAmount());
		Integer originalAmt = Optional.ofNullable(reCalcOrderAmountDIO.getOrderAmountDIO().getOriginalAmount())
				.orElse(0);

		if (CollectionUtil.isNullOrEmpty(reCalcOrderAmountDIO.getOrderDiscountList())
				&& Objects.equals(currOriginalAmt,originalAmt)) {
			return true;
		}

		return false;
	}
}
